package com.ean.backpack.controller;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ean.backpack.core.util.CoreUtils;
import com.ean.backpack.core.util.CoreUtils.UtilFormat;
import com.ean.backpack.dto.SearchFormDTO;
import com.ean.backpack.other.DestinationFormatter;
import com.ean.backpack.validator.SearchFormValidator;
import com.ean.backpack.wsapi.HotelListOption;
import com.ean.backpack.wsapi.HotelListRequest;
import com.ean.backpack.wsapi.HotelListResponse;
import com.ean.backpack.wsapi.HotelServices;
import com.ean.backpack.wsapi.HotelServicesImplService;
import com.ean.backpack.wsapi.LocaleType;
import com.ean.backpack.wsapi.Room;
import com.ean.backpack.wsapi.RoomGroup;
import com.ean.backpack.wsapi.SortType;
import com.ean.backpack.wsapi.SupplierCacheTolerance;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

@Controller
public class SearchController extends AbstractController {

	@Autowired
	@Qualifier("hotelService")
	private HotelServicesImplService service;

	@Autowired
	private SearchFormValidator validator;

	@Autowired
	private ApplicationContext applicationContext;

	@InitBinder(value = "search")
	protected void initBinder(WebDataBinder binder) {
		binder.setValidator(validator);
	}

	/**
	 * Renders the index view it via freemarker * template.
	 * 
	 * @param model
	 * @return the index view (FTL)
	 */
	@RequestMapping(value = "/search", method = RequestMethod.GET)
	public String index(@ModelAttribute("model") ModelMap model,
			@ModelAttribute("search") @Valid SearchFormDTO search,
			BindingResult result) {
		List<String> search_error = new ArrayList<String>();
		DestinationFormatter formatter = new DestinationFormatter();
		formatter.process(search.getDestination(), ",");

		if (result.hasErrors()) {
			List<String> date_error = new ArrayList<String>();
			List<String> adults_error = new ArrayList<String>();
			List<String> children_error = new ArrayList<String>();
			List<String> age_error = new ArrayList<String>();

			List<ObjectError> allObjectErrors = null;

			allObjectErrors = result.getAllErrors();

			for (ObjectError objectError : allObjectErrors) {

				if (objectError.getCode().toString().contains("destination")) {
					search_error.add(objectError.getCode().toString());
				}
				if (objectError.getCode().toString().contains("Date")) {
					date_error.add(objectError.getCode().toString());
				}
				if (objectError.getCode().toString().contains("adultsCount")) {
					adults_error.add(objectError.getCode().toString());
				}
				if (objectError.getCode().toString().contains("childrenCount")) {
					children_error.add(objectError.getCode().toString());
				}
				if (objectError.getCode().toString().contains("childAge")) {
					age_error.add(objectError.getCode().toString());
				}
			}

			logger.info(search.toString());

			model.put("search_error", search_error);
			model.put("date_error", date_error);
			model.put("adults_error", adults_error);
			model.put("children_error", children_error);
			model.put("age_error", age_error);
			model.put("hasErrors", result.hasErrors());

			return "index";
		} else if(formatter.getCity() != "" || formatter.isValidDestination()) {
			HotelServices port = service.getHotelServicesImplPort();

			RoomGroup rooms = new RoomGroup();
			Room room1 = new Room();
			room1.setNumberOfAdults(search.getRooms().get(0).getAdultsCount());
			room1.setNumberOfChildren(search.getRooms().get(0)
					.getChildrenCount());
			if (room1.getNumberOfChildren() != 0) {
				room1.getChildAges().addAll(
						search.getRooms().get(0).getChildAges());
			}
			rooms.getRoom().add(room1);

			HotelListRequest hotelList = new HotelListRequest();
			hotelList.setApiKey("cbrzfta369qwyrm9t5b8y8kf");
			hotelList.setCid(55505);
			hotelList.setLocale(LocaleType.EN_US);
			hotelList.setMinorRev(22);
			hotelList.setCurrencyCode("USD");
			hotelList.setCustomerIpAddress("");
			hotelList.setCustomerUserAgent("");
			hotelList.setArrivalDate(CoreUtils.convertDate(
					search.getStartDate(), UtilFormat.ddmmyyyy,
					UtilFormat.mmddyyyy, "/"));
			hotelList.setDepartureDate(CoreUtils.convertDate(
					search.getEndDate(), UtilFormat.ddmmyyyy,
					UtilFormat.mmddyyyy, "/"));
			hotelList.setNumberOfResults(10);
			hotelList.setRoomGroup(rooms);
			hotelList.setIncludeDetails(true);
			// Methos search by city/state/country
			hotelList.setCity(formatter.getCity());
			hotelList.setStateProvinceCode(formatter.getState());
			hotelList.setCountryCode(formatter.getCountry());
			// Filters

			hotelList.setSort(SortType.PROMO);
			hotelList.getOptions().add(HotelListOption.DEFAULT);
			hotelList.setSupplierCacheTolerance(SupplierCacheTolerance.MIN_ENHANCED);
			
			/* Execution time - debug only */
			long tmp = System.currentTimeMillis();
			logger.info(tmp);
			HotelListResponse hotelRes = port.getList(hotelList);
			logger.info(System.currentTimeMillis() - tmp);

			model.put("hotels", hotelRes);
			
			return "pages/search/search_hotels";
		} else {
			search_error.add("destination.invalid");
			model.put("search_error", search_error);
			return "index";
		}

	}

	@RequestMapping(value = "/ajaxinfo", method = RequestMethod.POST)
	public @ResponseBody
	String getAjaxInfo() {
		String content = "";
		try {
			String classPath = new DefaultResourceLoader().getResource("")
					.getFile().getPath();
			String templatePath = classPath.replace("classes", "ftl");
			Configuration cfg = new Configuration();
			cfg.setDirectoryForTemplateLoading(new File(templatePath));

			Map<String, String> model1 = new HashMap<String, String>();
			model1.put("pingStatus", "test from backend");

			Template template = cfg.getTemplate("wsapi.ftl");

			content = renderTemplate(template, model1);

			logger.info(classPath);
			logger.info(content);
		} catch (Exception e) {
			logger.error("could not get the template content");
		}

		return content;
	}

	private static String renderTemplate(Template template, Object model)
			throws TemplateException, IOException {
		StringWriter result = new StringWriter();
		template.process(model, result);
		return result.toString();
	}

}
